// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "AbilitySystem/LyraAbilitySet.h"
#include "Components/PawnComponent.h"
#include "Net/Serialization/FastArraySerializer.h"

#include "LyraEquipmentManagerComponent.generated.h"

#define UE_API LYRAGAME_API

class UActorComponent;
class ULyraAbilitySystemComponent;
class ULyraEquipmentDefinition;
class ULyraEquipmentInstance;
class ULyraEquipmentManagerComponent;
class UObject;
struct FFrame;
struct FLyraEquipmentList;
struct FNetDeltaSerializeInfo;
struct FReplicationFlags;

/** 单个已应用的装备条目 */
USTRUCT(BlueprintType)
struct FLyraAppliedEquipmentEntry : public FFastArraySerializerItem
{
	GENERATED_BODY()

	FLyraAppliedEquipmentEntry()
	{}

	FString GetDebugString() const; // 获取调试字符串

private:
	friend FLyraEquipmentList;
	friend ULyraEquipmentManagerComponent;

	// 被装备的装备类
	UPROPERTY()
	TSubclassOf<ULyraEquipmentDefinition> EquipmentDefinition; // 装备定义类

	UPROPERTY()
	TObjectPtr<ULyraEquipmentInstance> Instance = nullptr; // 装备实例

	// 仅权威端：授予的句柄列表
	UPROPERTY(NotReplicated)
	FLyraAbilitySet_GrantedHandles GrantedHandles; // 授予的能力句柄
};

/** 已应用的装备列表 */
USTRUCT(BlueprintType)
struct FLyraEquipmentList : public FFastArraySerializer
{
	GENERATED_BODY()

	FLyraEquipmentList()
		: OwnerComponent(nullptr)
	{
	}

	FLyraEquipmentList(UActorComponent* InOwnerComponent)
		: OwnerComponent(InOwnerComponent)
	{
	}

public:
	//~FFastArraySerializer 契约
	void PreReplicatedRemove(const TArrayView<int32> RemovedIndices, int32 FinalSize); // 复制移除前
	void PostReplicatedAdd(const TArrayView<int32> AddedIndices, int32 FinalSize); // 复制添加后
	void PostReplicatedChange(const TArrayView<int32> ChangedIndices, int32 FinalSize); // 复制更改后
	//~FFastArraySerializer 契约结束

	bool NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParms) // 网络增量序列化
	{
		return FFastArraySerializer::FastArrayDeltaSerialize<FLyraAppliedEquipmentEntry, FLyraEquipmentList>(Entries, DeltaParms, *this);
	}

	ULyraEquipmentInstance* AddEntry(TSubclassOf<ULyraEquipmentDefinition> EquipmentDefinition); // 添加条目
	void RemoveEntry(ULyraEquipmentInstance* Instance); // 移除条目

private:
	ULyraAbilitySystemComponent* GetAbilitySystemComponent() const; // 获取能力系统组件

	friend ULyraEquipmentManagerComponent;

private:
	// 复制的装备条目列表
	UPROPERTY()
	TArray<FLyraAppliedEquipmentEntry> Entries; // 条目数组

	UPROPERTY(NotReplicated)
	TObjectPtr<UActorComponent> OwnerComponent; // 所有者组件
};

template<>
struct TStructOpsTypeTraits<FLyraEquipmentList> : public TStructOpsTypeTraitsBase2<FLyraEquipmentList>
{
	enum { WithNetDeltaSerializer = true }; // 支持网络增量序列化
};

/**
 * 管理应用于 pawn 的装备
 */
UCLASS(MinimalAPI, BlueprintType, Const)
class ULyraEquipmentManagerComponent : public UPawnComponent
{
	GENERATED_BODY()

public:
	UE_API ULyraEquipmentManagerComponent(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());

	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly)
	UE_API ULyraEquipmentInstance* EquipItem(TSubclassOf<ULyraEquipmentDefinition> EquipmentDefinition); // 装备物品

	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly)
	UE_API void UnequipItem(ULyraEquipmentInstance* ItemInstance); // 卸下物品

	//~UObject 接口
	UE_API virtual bool ReplicateSubobjects(class UActorChannel* Channel, class FOutBunch* Bunch, FReplicationFlags* RepFlags) override; // 复制子对象
	//~UObject 接口结束

	//~UActorComponent 接口
	UE_API virtual void InitializeComponent() override; // 初始化组件
	UE_API virtual void UninitializeComponent() override; // 取消初始化组件
	UE_API virtual void ReadyForReplication() override; // 准备复制
	//~UActorComponent 接口结束

	/** 返回给定类型的第一个装备实例，如果未找到则返回 nullptr */
	UFUNCTION(BlueprintCallable, BlueprintPure)
	UE_API ULyraEquipmentInstance* GetFirstInstanceOfType(TSubclassOf<ULyraEquipmentInstance> InstanceType); // 获取类型的第一个实例

 	/** 返回给定类型的所有装备实例，如果未找到则返回空数组 */
 	UFUNCTION(BlueprintCallable, BlueprintPure)
	UE_API TArray<ULyraEquipmentInstance*> GetEquipmentInstancesOfType(TSubclassOf<ULyraEquipmentInstance> InstanceType) const; // 获取类型的所有实例

	template <typename T>
	T* GetFirstInstanceOfType() // 模板方法：获取类型的第一个实例
	{
		return (T*)GetFirstInstanceOfType(T::StaticClass());
	}

private:
	UPROPERTY(Replicated)
	FLyraEquipmentList EquipmentList; // 装备列表
};

#undef UE_API